#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <unistd.h>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <fstream>
#include <map>
#include <vector>
#include <errno.h>
#include "Point.h"
#include "Constantes.h"
#include <math.h>

using namespace std;


//! La classe Serveur permet de définir le comportement du serveur dans notre reseau.
/*!
 Le serveur sert à initiliaser le réseau, c'est à dire qu'il doit informé tous les routeurs qui se connectent à lui en leurs donnant un numéro d'identification et la liste de leurs voisins.
 */
class Serveur {	
    
private:
    
    //! Socket du Routeur.
    int socketEcoute;
    //! Taille de l'adresse du serveur.
    socklen_t tailleAdresseServeur;
    //! Taille de l'adresse du client.
    socklen_t tailleAdresseClient;
    //! Adresse du serveur.
    struct sockaddr_in adresseServeur; 
    //! Adresse du client.
    struct sockaddr_in adresseClient;
    //! Adresse du processus generateur de perte.
    struct sockaddr_in adresseProcessusPerte;

    //! Correspondance en l'adresse des routeurs et leurs numéro d'identification.
	map<int, struct sockaddr_in> adressesClients;
	
    //! Thread permettant de gérer les demandes des clients.
	pthread_t threadGestionClient;
    
    //! Message par lequel la communication se fera avec le client.
    char message[TAILLE_MESSAGE];
    //! Nombre de routeur dans le réseau.
    int nbRouteur;
    //! Id du routeur courant.
    int idRouteur;
    //! Graphe des liaisons entre les routeurs.
    float **graphe;
    
    
public:
    
    //! Constructeur basic permettant de créer un nouveau serveur.
    Serveur();
    
    //! Destructeur de la classe Serveur.
    ~Serveur();
    
    
    //! Initialise le serveur en lui créant une socket.
    void initServeur();
    
    //! Lance le serveur qui attendra la connexion d'un routeur et qui traitera sa demande en lui donnant ca liste de voisins et son numéro d'identification.
    /*!
     Pour chaque connexion d'un routeur le serveur va créer un nouveau thread qui sera associé au client et qui traitera sa demande pour ne pas perturber les autres demande des routeurs.
     */
    void lancementServeur();
    
    //! Envoie une adresse avec son numéro d'identification au processus de perte (processus aléatoire).
    /*!
     \param adresse 
     */
    void envoieAdresseProcessusPerte(struct sockaddr_in adresse);
    
    //! Calcule les voisins d'un routeur.
    /*!
     \param idRouteur 
     \param voisin 
     */
    void calculerVoisin(int idRouteur, char *voisin);
    
    // TODO: A compléter...
	void gestionClient();
    
    //! Ouvre et analyse le fichier où il est décri le graphe du réseau.
    /*!
     \param url l'url du fichier à ouvrir.
     */
    void ouvrirFichier(string url);	
	
    
    // TODO: A compléter...
	static void* runGestionClient(void *arg);
};
